package com.elitel.frame.business.service.impl;

import com.elitel.common.CustomHttpServletRequestWrapper;
import com.elitel.common.utils.SpringUtils;
import com.elitel.frame.base.service.BaseServicesService;
import com.elitel.frame.base.service.SysPrjServiceService;
import com.elitel.frame.business.service.common.CommonServer;
import com.elitel.frame.main.entity.BaseServices;
import com.elitel.frame.main.entity.SysPrjservice;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.web.method.HandlerMethod;
import org.springframework.web.servlet.mvc.method.RequestMappingInfo;
import org.springframework.web.servlet.mvc.method.annotation.RequestMappingHandlerMapping;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.InvocationTargetException;
import java.util.Map;
import java.util.Set;

@Service
public class SingleTableSqlPolymerServer implements CommonServer {

    private static final Logger logger = LoggerFactory.getLogger(SingleTableSqlPolymerServer.class);

    /**
     * 发起请求
     *
     * @param params
     * @param request
     * @param response
     * @return 正常情况下 这里不应该将返回值封装到JsonDataResult中，应该统一在Controller中封装
     */
    @Override
    public Object doRequest(Object params, HttpServletRequest request, HttpServletResponse response) {
        logger.info("Sql查询服务执行了 参数是:{}", params);
        try {
            // 因为之前的服务把业务逻辑写到了Controller中, 所以这里需要从Spring容器中获取Bean
            return requestServiceData(request, (Map) params);
        } catch (Exception e) {
            throw new RuntimeException(e.getMessage());
        }
    }


    /**
     * 获取服务数据
     *
     * @param request
     * @param params
     * @return
     * @throws InvocationTargetException
     * @throws IllegalAccessException
     */
    private Object requestServiceData(HttpServletRequest request, Map params) throws InvocationTargetException, IllegalAccessException {

        // 根据serviceCode获取serviceurl
        String serviceCode = (String) params.get("serviceID");
        SysPrjServiceService sysPrjServiceService = SpringUtils.getBean(SysPrjServiceService.class);
        SysPrjservice sysPrjservice = sysPrjServiceService.getSysPrjserviceByServiceCode(serviceCode);
        String serviceType = sysPrjservice.getServicetype();
        BaseServicesService bean = SpringUtils.getBean(BaseServicesService.class);
        BaseServices serverByGuid = bean.getServerByGuid(serviceType);
        String serviceurl = serverByGuid.getServiceurl();

        // 将参数进行重新封装到parameter和parameterMap中
        CustomHttpServletRequestWrapper requestWrapper = new CustomHttpServletRequestWrapper(request);
        Map<String, String[]> parameterMap = requestWrapper.getParameterMap();
        params.forEach((k, v) -> {
            parameterMap.put(String.valueOf(k), new String[]{String.valueOf(v)});
            requestWrapper.setParameter(String.valueOf(k), String.valueOf(v));
        });


        HandlerMethod handlerMethod = null;
        RequestMappingHandlerMapping requestMappingHandlerMapping = SpringUtils.getBean(RequestMappingHandlerMapping.class);
        // 获取 RequestMapping中的全部方法
        Map<RequestMappingInfo, HandlerMethod> handlerMethodMap = requestMappingHandlerMapping.getHandlerMethods();
        for (RequestMappingInfo requestMappingInfo : handlerMethodMap.keySet()) {
            //获取所有的URL
            Set<String> urlSet = requestMappingInfo.getPatternsCondition().getPatterns();
            if (!ObjectUtils.isEmpty(urlSet) && urlSet.contains(serviceurl)) {
                handlerMethod = handlerMethodMap.get(requestMappingInfo);
                break;
            }
        }
        if (handlerMethod != null) {
            //获取当前Controller对应的 beanName
            String beanName = String.valueOf(handlerMethod.getBean());
            return handlerMethod.getMethod().invoke(SpringUtils.getBean(beanName),
                    requestWrapper, serviceCode,
                    ObjectUtils.isEmpty(params.get("pageNO"))?null:params.get("pageNO").toString(),
                    ObjectUtils.isEmpty(params.get("pageSize"))?null:params.get("pageSize").toString(),
                    null, null);
        }
        return null;
    }
}
